package command;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * Util for use reflection to get Object
 * @author Jeff Zhuo
 *
 */
public class ReflectUtil {

	/**
	 * Get the Object by the name of class
	 * 
	 * @param classname
	 *            The complete name of the class
	 * @return
	 */
	public static Object newObjectInstance(String classname) {
		Object instance = null;
		try {
			Class<?> classType = Class.forName(classname);

			instance = classType.newInstance();
		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException e) {
			e.printStackTrace();
		}

		return instance;
	}

	/**
	 * Get the Object by the name of class
	 * 
	 * @param classname
	 *            The complete name of the class
	 * @param params
	 *            The params of the constructor
	 * @return
	 */
	public static Object newObjectInstanceWithParams(String classname,
			Object[] params) {
		Object instance = null;
		try {

			Class<?> classType = Class.forName(classname);

			Constructor<?>[] consts = classType.getConstructors();
			List<Constructor<?>> constructors = new ArrayList<>();
			for (Constructor<?> const1 : consts) {
				int paramsLength = const1.getParameterAnnotations().length;
				// Get the constructors by the count of parameters
				if (paramsLength == params.length) {
					constructors.add(const1);
				}
			}

			if (constructors.size() > 0) {
				Class<?>[] types = null;
				for (Constructor<?> constr : constructors) {
					Class<?>[] paramTypes = constr.getParameterTypes();

					boolean equal = true;

					for (int i = 0; i < paramTypes.length; i++) {

						// Using simple name to get the constructor
						if (!paramTypes[i].getSimpleName().equalsIgnoreCase(params[i].getClass().getSimpleName())) {
							equal = false;
							break;
						}
					}

					if (equal == true) {
						types = paramTypes;
						break;
					}

				}

				if (types != null) {
					instance = classType.getConstructor(types).newInstance(
							params);
				}
			}

		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | NoSuchMethodException
				| SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return instance;
	}
}
